#######################################################
# Example of FRTDEVS Coupled model for a two-slot toaster 
# Author: moonho.hwang@gmail.com
#   Date: Oct.19.2011
#######################################################
from XSY.DEVS.FRTDEVS import * 
from XSY.DEVS.CoupledDEVS import *
from XSY.Set.Interval import *
from XSY.DEVS.ReachGen import *
from XSY.DEVS.SimEngine import SimEngine
from XSY.DEVS.VeriEngine import VeriEngine

class Toaster(FRTDEVS):
   '''an atomic FRTDEVS for a toaster'''
   def __init__(m, n, tl, tu, parent=None):
      '''constructor'''
      FRTDEVS.__init__(m, n, parent) 
      m.addInputPorts('?push')
      m.addOutputPorts('!pop')
      m.tl = tl
      m.tu = tu

   def delta_0(m):
      '''initial state'''
      m.phase = 'I'

   def rv_tau(m):
      '''lifespan range function'''
      if m.phase == 'T':
         return TInterval(m.tl,m.tu) # continuous random variable distributed uniformly 
      else:
         return float('inf') # discrete random variable with certainty 

   def delta_x(m, x):
      '''external transition function'''
      if x.port == m.IP['?push'] and m.phase == 'I':
         m.phase = 'T'
         return True
      else: # else ignoring 
         return False
               
   def delta_y(m):
      '''output and internal transition function'''
      if m.phase == 'T':
         m.phase = 'I'
         return PortValue(m.OP["!pop"])
   
   def get_state(m):
      '''get the state'''
      return m.phase

   def set_state(m, s):
      '''set the state as s'''
      m.phase = s

def make_input_event(md):
   ''' a callback function for injection'''
   return md, PortValue(md.IP['?push'])

def runSimulation(md):
   engine = SimEngine(md1, make_input_event)

   #---- setting StepByStep and DES simulation only ----
   engine.StepByStep = True
   engine.sfactor = float('inf')
   #----------------------------------------------------
   engine.runInteractiveMenu()

def runVerification(md):
   X = []
   X.append(PortValue(md.IP['?push']))

   VE = VeriEngine(md, X, None, None)
   VE.runtimeInteractiveMenu()

if __name__ == '__main__':
   md1 = Toaster("T1", 20,30) 

   c = True
   while c:
      s = raw_input('[s]im, [v]eri, e[x]it>')
      if s == 's' or s == 'sim': 
         runSimulation(md1)
      elif s == 'v' or s == 'veri':
         runVerification(md1)
      elif s == 'x' or s == 'exit':
         c = False
      else:
         print('%s is an invalid input!'%s)
      
   print "good bye~!" 
  
